<?php

namespace iBrand\Shop\Backend\Service;

use iBrand\Component\Goods\Models\Style;
use iBrand\Component\Goods\Models\Season;
use iBrand\Component\Order\Models\Adjustment;
use iBrand\Component\Order\Models\Order;
use iBrand\Shop\Core\Models\ShopOrder;
use iBrand\Shop\Core\Repositories\ShopOrderRepository;
use iBrand\Component\Order\Repositories\OrderRepository;
use iBrand\Store\Backend\Repositories\OrderItemRepository;
use DB;

class SalesReportService
{
    protected $orderItemRepository;
    protected $shopOrderRepository;
    protected $orderRepository;

    public function __construct(OrderItemRepository $orderItemRepository,
                                ShopOrderRepository $shopOrderRepository,
                                OrderRepository $orderRepository)
    {
        $this->orderItemRepository = $orderItemRepository;
        $this->shopOrderRepository = $shopOrderRepository;
        $this->orderRepository = $orderRepository;
    }

    public function getSaleDetailList(array $where, array $time, array $product_ids, $limit = 20, $type = 'list')
    {
        $query = $this->orderItemRepository->scopeQuery(function ($query) use ($where, $time, $product_ids) {
            if (!empty($where)) {
                foreach ($where as $key => $value) {
                    if ($key == 'order_no' || $key == 'channel_id') {
                        continue;
                    }

                    if (is_array($value)) {
                        list($operate, $va) = $value;
                        $query = $query->where($key, $operate, $va);
                    } else {
                        $query = $query->where($key, $value);
                    }
                }
            }

            if (!empty($time)) {
                foreach ($time as $key => $value) {
                    if (is_array($value)) {
                        list($operate, $va) = $value;
                        $query = $query->where($key, $operate, $va);
                    } else {
                        $query = $query->where($key, $value);
                    }
                }
            }

            if (!empty($product_ids)) {
                $query->whereIn('item_id', $product_ids);
            }

            $query = $query->whereHas('order', function ($query) use ($where) {
                $query = $query->where('channel', 'shop')->where('channel_id', $where['channel_id'])->where('status', Order::STATUS_PAY);
                if (isset($where['order_no'])) {
                    $query = $query->where('order_no', $where['order_no'][0], $where['order_no'][1]);
                }

                return $query;
            });

            return $query->orderBy('created_at', 'DESC');
        });

        if ($limit) {
            $list = $query->paginate($limit);
        } else {
            $list = $query->all();
        }

        if ($type == 'list') {
            foreach ($list as $item) {
                $item->goodsName = $item->product->goods->name;
                $item->goodsSn = $item->product->goods->goods_no;
                $item->barCode = $item->product->goods->goods_barcode;
                $item_meta = json_decode($item->item_meta, true);
                $item_meta = explode('-', $item_meta['specs_text']);
                $item->colorName = $item_meta[0];
                $item->sizeName = $item_meta[1];
                $item->categoryId = $item->product->goods->categories()->orderBy('id', 'DESC')->first()->id;
                $item->blandName = $item->product->goods->brand->id;
                $item->price = $item->unit_price;  //吊牌价
                $item->amount = $item->units_total / 100;  //吊牌总金额
                $item->purchasePrice = $item->product->goods->factory_price;  //采购价
                $item->costTotal = $item->purchasePrice * $item->quantity;  //采购总成本
                $item->trueAmount = $item->total;  //成交价
                $item->truePrice = $item->total / $item->quantity;  //成交均价
                $item->discount = ($item->total / ($item->units_total / 100)) * 100; //折扣(%)
                $item->ordersSn = $item->order->order_no;
                $shopOrder = $this->shopOrderRepository->findWhere(['order_id' => $item->order_id, 'shop_id' => session('shop_id')])->first();
                $item->salerName = isset($shopOrder->clerk->name) ? $shopOrder->clerk->name : '';
                $item->clientName = $item->order->order_user_name;
                $item->styleName = Style::where('id', $item->product->goods->style_id)->value('name');
                $item->seasonName = Season::where('id', $item->product->goods->season_id)->value('name');
                $item->year = $item->product->goods->year;
                $item->trueTotalAmount = $item->order->total;
                $item->alreadyPaid = $item->order->total;
                $item->businessTime = date('Y-m-d H:i', strtotime($item->created_at));
                $item->storeName = isset($shopOrder->shop->name) ? $shopOrder->shop->name : '';
                $item->remark = $item->order->note;

                $item->grossProfit = $item->total - $item->costTotal;
                $item->grossProfitRate = $item->total == 0 ? 0 : number_format(($item->grossProfit / $item->total) * 100, 2);
            }
        }

        return $list;
    }

    public function getSaleDetailListExportData($list)
    {
        $data = [];
        if ($list && $list->count() > 0) {
            $i = 0;
            foreach ($list as $item) {
                $data[$i][] = $item->goodsName;
                $data[$i][] = $item->goodsSn;
                $data[$i][] = $item->barCode;
                $data[$i][] = $item->colorName;
                $data[$i][] = $item->sizeName;
                $data[$i][] = $item->product->goods->categories()->orderBy('id', 'DESC')->first()->name;
                $data[$i][] = $item->blandName;
                $data[$i][] = $item->quantity;
                $data[$i][] = $item->price;
                $data[$i][] = $item->amount;
                $data[$i][] = $item->discount;
                $data[$i][] = $item->truePrice;
                $data[$i][] = $item->trueAmount;
                $data[$i][] = $item->purchasePrice;
                $data[$i][] = $item->costTotal;
                $data[$i][] = $item->grossProfit;
                $data[$i][] = $item->grossProfitRate;
                $data[$i][] = $item->ordersSn;
                $data[$i][] = $item->salerName;
                $data[$i][] = $item->clientName;
                $data[$i][] = $item->styleName;
                $data[$i][] = $item->seasonName;
                $data[$i][] = $item->year;
                $data[$i][] = $item->trueTotalAmount;
                $data[$i][] = $item->alreadyPaid;
                $data[$i][] = $item->businessTime;
                $data[$i][] = $item->storeName;
                $i++;
            }
        }

        return $data;
    }

    public function getSaleDetailListExportTitle()
    {
        return ['商品名称', '货号', '条码', '颜色', '尺码', '分类', '品牌', '单品数量', '吊牌价', '总金额', '折扣%', '折后价', '成交总金额', '采购均价', '采购成本', '毛利润', '毛利率%', '单据编号', '销售员', '客户', '款式', '季节', '年份', '单据总金额', '实收金额', '单据日期', '所属门店'];
    }

    public function getSaleGroupBySkuList(array $where, array $time, array $product_ids, $limit = 20, $type = 'list')
    {
        $query = $this->orderItemRepository->scopeQuery(function ($query) use ($where, $time, $product_ids) {

            if (!empty($where)) {
                foreach ($where as $key => $value) {
                    if ($key == 'order_no' || $key == 'channel_id' || $key == 'status') {
                        continue;
                    }

                    if (is_array($value)) {
                        list($operate, $va) = $value;
                        $query = $query->where($key, $operate, $va);
                    } else {
                        $query = $query->where($key, $value);
                    }
                }
            }

            if (!empty($time)) {
                foreach ($time as $key => $value) {
                    if (is_array($value)) {
                        list($operate, $va) = $value;
                        $query = $query->where($key, $operate, $va);
                    } else {
                        $query = $query->where($key, $value);
                    }
                }
            }

            if (!empty($product_ids)) {
                $query->whereIn('item_id', $product_ids);
            }

            $query = $query->whereHas('order', function ($query) use ($where) {
                $query->where('channel', 'shop')->where('channel_id', $where['channel_id'])->where('status', Order::STATUS_PAY);
            });

            return $query->groupBy('item_id')->orderBy('created_at', 'DESC');
        });

        if ($limit) {
            $list = $query->paginate($limit, ['*', DB::raw('sum(quantity) as total_quantity'), DB::raw('sum(total) as total_amount')]);
        } else {
            $list = $query->all(['*', DB::raw('sum(quantity) as total_quantity'), DB::raw('sum(total) as total_amount')]);
        }

        if ($type == 'list') {
            foreach ($list as $item) {
                $item->quantity = $item->total_quantity;
                $item->goodsName = $item->product->goods->name;
                $item->goodsSn = $item->product->goods->goods_no;
                $item->barCode = $item->product->goods->goods_barcode;
                $item_meta = json_decode($item->item_meta, true);
                $item_meta = explode('-', $item_meta['specs_text']);
                $item->colorName = $item_meta[0];
                $item->sizeName = $item_meta[1];
                $item->categoryId = $item->product->goods->categories()->orderBy('id', 'DESC')->first()->id;
                $item->blandName = $item->product->goods->brand->id;
                $item->price = $item->unit_price;
                $item->purchasePrice = $item->product->goods->factory_price;
                $item->costTotal = $item->purchasePrice * $item->total_quantity;
                $item->amount = $item->units_total / 100;
                $item->styleName = Style::where('id', $item->product->goods->style_id)->value('name');
                $item->seasonName = Season::where('id', $item->product->goods->season_id)->value('name');
                $item->year = $item->product->goods->year;


                $item->trueAmount = $item->total_amount / 100;
                $item->discount = number_format(($item->trueAmount / ($item->price * $item->total_quantity)) * 100, 2);

                $item->grossProfit = $item->trueAmount - $item->costTotal;
                $item->grossProfitRate = $item->trueAmount == 0 ? 0 : number_format(($item->grossProfit / $item->trueAmount) * 100, 2, ".", "");
            }
        }

        return $list;
    }

    public function getSaleGroupBySkuListData($list)
    {
        $data = [];
        if ($list && $list->count() > 0) {
            $i = 0;
            foreach ($list as $item) {
                $data[$i][] = $item->goodsName;
                $data[$i][] = $item->goodsSn;
                $data[$i][] = $item->barCode;
                $data[$i][] = $item->colorName;
                $data[$i][] = $item->sizeName;
                $data[$i][] = $item->product->goods->categories()->orderBy('id', 'DESC')->first()->name;
                $data[$i][] = $item->blandName;
                $data[$i][] = $item->total_quantity;
                $data[$i][] = $item->price;
                $data[$i][] = $item->discount;
                $data[$i][] = $item->trueAmount;
                $data[$i][] = $item->purchasePrice;
                $data[$i][] = $item->costTotal;
                $data[$i][] = $item->grossProfit;
                $data[$i][] = $item->grossProfitRate;
                $data[$i][] = $item->styleName;
                $data[$i][] = $item->seasonName;
                $data[$i][] = $item->year;
                $i++;
            }
        }

        return $data;
    }

    public function getSaleGroupBySkuListTitle()
    {
        return ['商品名称', '货号', '条码', '颜色', '尺码', '分类', '品牌', '单品数量', '吊牌价', '折扣', '成交总金额', '采购均价', '采购成本', '毛利润', '毛利率%', '款式', '季节', '年份'];
    }

    public function getSaleGroupByOrderList(array $where, array $time, $limit = 20, $type = 'list')
    {
        $query = $this->orderRepository->scopeQuery(function ($query) use ($where, $time) {
            if (!empty($where)) {
                foreach ($where as $key => $value) {
                    if (is_array($value)) {
                        list($operate, $va) = $value;
                        $query = $query->where($key, $operate, $va);
                    } else {
                        $query = $query->where($key, $value);
                    }
                }
            }

            if (!empty($time)) {
                foreach ($time as $key => $value) {
                    if (is_array($value)) {
                        list($operate, $va) = $value;
                        $query = $query->where($key, $operate, $va);
                    } else {
                        $query = $query->where($key, $value);
                    }
                }
            }

            return $query->orderBy('created_at', 'DESC');
        });

        if ($limit) {
            $list = $query->paginate($limit);
        } else {
            $list = $query->all();
        }

        if ($type == 'list') {
            foreach ($list as $item) {
                $item->quantity = $item->count;
                $item->ordersSn = $item->order_no;
                $shopOrder = $this->shopOrderRepository->findWhere(['order_id' => $item->id, 'shop_id' => session('shop_id')])->first();
                $item->salerName = isset($shopOrder->clerk) ? $shopOrder->clerk->name : '';
                $item->clientName = $item->order_user_name;
                $item->trueTotalAmount = $item->items_total_yuan;
                $item->adjustmentsTotal = $item->adjustments_total_yuan;

                $item->otherCost = 0;
                $item->otherAccountItemName = '';
                $item->alreadyPaid = $item->total_yuan;
                $item->businessTime = date('Y-m-d H:i', strtotime($item->created_at));
                $item->storeName = isset($shopOrder->shop) ? $shopOrder->shop->name : '';

                $cost_price = 0;
                foreach ($item->items as $order_item) {
                    $cost_price += $order_item->getFactoryPrice();
                }
                $item->costTotal = $cost_price;
                $item->grossProfit = $item->total_yuan - $item->costTotal;
                $item->grossProfitRate = $item->total_yuan == 0 ? 0 : number_format(($item->grossProfit / $item->total_yuan) * 100, 2);
            }
        }

        return $list;
    }

    public function getSaleGroupByOrderListData($list)
    {
        $data = [];
        if ($list && $list->count() > 0) {
            $i = 0;
            foreach ($list as $item) {
                $data[$i][] = $item->ordersSn;
                $data[$i][] = $item->quantity;
                $data[$i][] = $item->costTotal;
                $data[$i][] = $item->grossProfit;
                $data[$i][] = $item->grossProfitRate;
                $data[$i][] = $item->salerName;
                $data[$i][] = $item->clientName;
                $data[$i][] = $item->trueTotalAmount;
                $data[$i][] = $item->adjustmentsTotal;
                $data[$i][] = $item->alreadyPaid;
                $data[$i][] = $item->businessTime;
                $data[$i][] = $item->storeName;
                $i++;
            }
        }

        return $data;
    }

    public function getSaleGroupByOrderListTitle()
    {
        return ['单据编号', '单品数量', '采购成本', '毛利润', '毛利率%', '销售员', '客户', '单据总金额', '总优惠金额', '实收金额', '单据日期', '所属门店'];
    }

    public function getSaleGroupByClientList(array $where, array $time, $limit = 20, $type = 'list')
    {
        $query = $this->orderRepository->scopeQuery(function ($query) use ($where, $time) {
            if (!empty($where)) {
                foreach ($where as $key => $value) {
                    if (is_array($value)) {
                        list($operate, $va) = $value;
                        $query = $query->where($key, $operate, $va);
                    } else {
                        $query = $query->where($key, $value);
                    }
                }
            }

            if (!empty($time)) {
                foreach ($time as $key => $value) {
                    if (is_array($value)) {
                        list($operate, $va) = $value;
                        $query = $query->where($key, $operate, $va);
                    } else {
                        $query = $query->where($key, $value);
                    }
                }
            }

            return $query->groupBy('user_id')->orderBy('created_at', 'DESC');
        });

        if ($limit) {
            $list = $query->paginate($limit, [DB::raw('GROUP_CONCAT(id) as ids'), DB::raw('sum(count) as total_count'), DB::raw('sum(total) as total_amount')]);
        } else {
            $list = $query->all([DB::raw('GROUP_CONCAT(id) as ids'), DB::raw('sum(count) as total_count'), DB::raw('sum(total) as total_amount')]);
        }

        if ($type == 'list') {
            foreach ($list as $item) {
                $item->quantity = $item->total_count;
                $item->clientName = $item->order_user_name;
                $item->trueAmount = $item->total_amount / 100;

                $ids = explode(',', $item->ids);
                $orders = Order::whereIn('id', $ids)->get();

                $costTotal = 0;
                foreach ($orders as $order) {
                    $factory_price_total = 0;
                    foreach ($order->items as $subItem) {
                        $factory_price = $subItem->getModel()->goods->factory_price;
                        $factory_price_total += $factory_price * $subItem->quantity;
                    }
                    $costTotal += $factory_price_total;
                }
                $item->costTotal = $costTotal;
                $item->grossProfit = $item->trueAmount - $item->costTotal;
                $item->grossProfitRate = $item->trueAmount == 0 ? 0 : number_format(($item->grossProfit / $item->trueAmount) * 100, 2, ".", "");

            }
        }

        return $list;
    }

    public function getSaleGroupByClientListData($list)
    {
        $data = [];
        if ($list && $list->count() > 0) {
            $i = 0;
            foreach ($list as $item) {
                $data[$i][] = $item->quantity;
                $data[$i][] = $item->trueAmount;
                $data[$i][] = $item->costTotal;
                $data[$i][] = $item->grossProfit;
                $data[$i][] = $item->grossProfitRate;
                $data[$i][] = $item->clientName;
                $i++;
            }
        }

        return $data;
    }

    public function getSaleGroupByClientListTitle()
    {
        return ['单品数量', '成交总金额', '采购成本', '毛利润', '毛利率%', '客户'];
    }

    public function getSaleGroupBySalerList(array $where, array $time, $limit = 20, $type = 'list')
    {
        $query = $this->shopOrderRepository->scopeQuery(function ($query) use ($where, $time) {
            if (!empty($where)) {
                foreach ($where as $key => $value) {
                    if (is_array($value)) {
                        list($operate, $va) = $value;
                        $query = $query->where($key, $operate, $va);
                    } else {
                        $query = $query->where($key, $value);
                    }
                }
            }

            if (!empty($time)) {
                foreach ($time as $key => $value) {
                    if (is_array($value)) {
                        list($operate, $va) = $value;
                        $query = $query->where($key, $operate, $va);
                    } else {
                        $query = $query->where($key, $value);
                    }
                }
            }

            return $query->with('order')->groupBy('clerk_id')->orderBy('created_at', 'DESC');
        });

        if ($limit) {
            $list = $query->paginate($limit, ['*', DB::raw('GROUP_CONCAT(order_id) as order_ids')]);
        } else {
            $list = $query->all(['*', DB::raw('GROUP_CONCAT(order_id) as order_ids')]);
        }


        if ($type == 'list') {
            foreach ($list as $item) {
                $ids = explode(',', $item->order_ids);
                $orders = Order::whereIn('id', $ids)->get();

                $item->quantity = $orders->sum('count');
                $total = $orders->sum('total');
                $item->trueAmount = $total / 100;
                $item->salerName = isset($item->clerk) ? $item->clerk->name : '';
                $item->storeName = isset($item->shop) ? $item->shop->name : '';

                $costTotal = 0;
                foreach ($orders as $order) {
                    $factory_price_total = 0;
                    foreach ($order->items as $subItem) {
                        $factory_price = $subItem->getModel()->goods->factory_price;
                        $factory_price_total += $factory_price * $subItem->quantity;
                    }
                    $costTotal += $factory_price_total;
                }
                $item->costTotal = $costTotal;
                $item->grossProfit = $item->trueAmount - $item->costTotal;
                $item->grossProfitRate = $item->trueAmount == 0 ? 0 : number_format(($item->grossProfit / $item->trueAmount) * 100, 2, ".", "");

            }
        }

        return $list;
    }

    public function getSaleGroupBySalerListData($list)
    {
        $data = [];
        if ($list && $list->count() > 0) {
            $i = 0;
            foreach ($list as $item) {
                $data[$i][] = $item->quantity;
                $data[$i][] = $item->trueAmount;
                $data[$i][] = $item->costTotal;
                $data[$i][] = $item->grossProfit;
                $data[$i][] = $item->grossProfitRate;
                $data[$i][] = $item->salerName;
                $data[$i][] = $item->storeName;
                $i++;
            }
        }

        return $data;
    }

    public function getSaleGroupBySalerListTitle()
    {
        return ['单品数量', '成交总金额', '采购成本', '毛利润', '毛利率%', '销售员', '所属门店'];
    }

    public function getSaleGroupByComStoreList(array $where, array $time, $limit = 20, $type = 'list')
    {
        $query = $this->shopOrderRepository->scopeQuery(function ($query) use ($where, $time) {
            if (!empty($where)) {
                foreach ($where as $key => $value) {
                    if (is_array($value)) {
                        list($operate, $va) = $value;
                        $query = $query->where($key, $operate, $va);
                    } else {
                        $query = $query->where($key, $value);
                    }
                }
            }

            if (!empty($time)) {
                foreach ($time as $key => $value) {
                    if (is_array($value)) {
                        list($operate, $va) = $value;
                        $query = $query->where($key, $operate, $va);
                    } else {
                        $query = $query->where($key, $value);
                    }
                }
            }

            return $query->with('order')->groupBy('shop_id')->orderBy('created_at', 'DESC');
        });

        if ($limit) {
            $list = $query->paginate($limit);
        } else {
            $list = $query->all();
        }

        if ($type == 'list') {
            foreach ($list as $item) {
                $order_ids = ShopOrder::where('shop_id', $item->shop_id)->pluck('order_id');
                $item->quantity = Order::whereIn('id', $order_ids->all())->sum('count');
                $total = Order::whereIn('id', $order_ids->all())->sum('total');
                $item->trueAmount = $total / 100;
                $item->storeName = isset($item->shop) ? $item->shop->name : '';
            }
        }

        return $list;
    }

    public function getSaleGroupByComStoreListData($list)
    {
        $data = [];
        if ($list && $list->count() > 0) {
            $i = 0;
            foreach ($list as $item) {
                $data[$i][] = $item->quantity;
                $data[$i][] = $item->trueAmount;
                $data[$i][] = 0;
                $data[$i][] = 0;
                $data[$i][] = $item->storeName;
                $i++;
            }
        }

        return $data;
    }

    public function getSaleGroupByComStoreListTitle()
    {
        return ['单品数量', '总金额', '毛利润', '毛利率%', '所属门店'];
    }
}